home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-07-09 | 7.4 KB | 186 lines | [TEXT/CWIE] |
- /*
- AtExitToShell.c
-
- void YourFunction(void);
-
- error=AtExitToShell(YourFunction);
-
- AtExitToShell(YourFunction) requests that your function be called when the
- application quits, i.e. calls the ExitToShell trap, which tells the MacOS that
- it's done. Your function must have no arguments and no return value.
-
- This works fine both as 68K code and as PPC code. When using the Code Fragment
- Manager, you could instead use the CodeWarrior Preferences panel to install your
- own CFM Termination routine, as suggested in the CSMP postings below, but I
- haven't tried that.
-
- (MATLAB: If you compile this file as a MEX resource, to be called from MATLAB,
- then your call to AtExitToShell is a request that your function be called when
- the MEX resource is flushed from memory.)
-
- Many VideoToolbox routines set up interrupt service routines that must be killed
- before the program goes away. We want to kill these whether we quit via exit(),
- abort(), or the ExitToShell trap is invoked directly, e.g. if user types "ES"
- in MacsBug. The only way to be sure of killing something before the application
- goes away is to attach its killer, by patching, to the ExitToShell trap. That's
- what's done here.
-
- AtExitToShell() is closely modeled on the ANSI function atexit(). I wrote it to
- overcome the restrictive implementation of atexit() and _atexit() in CodeWarrior:
- they only invoke your functions if the ANSI function exit() is called, NOT if
- you call abort(), or the user types "ES" in MacsBug. I think that AtExitToShell
- is equivalent to the non-ANSI _atexit() routine provided by the Symantec THINK C
- environment.
-
- The registration list (of user functions) is last-in, first-out. When you
- eventually quit, your functions will be called in reverse of the order in which
- you registered them. No checking is made for duplication: the same function may
- be registed multiple times, and will be called multiple times.
-
- CAUTION: your application's runtime environment (e.g. stdio) will normally have
- shut itself down by the time it calls ExitToShell(), so a function scheduled for
- that time should not assume the availability of such services (e.g. printf).
- There's no restriction on the use of MacOS services.
-
- MATLAB: the Standard C atexit() and THINK C _atexit() routines should not be
- used in MATLAB code resources, because they aren't designed to handle the
- situation of code that may be flushed any time MATLAB executes "clear mex" or
- "clear all", at a time unrelated to exiting of the MATLAB application itself.
- Instead, MATLAB provides mexAtExit(), which allows you to register one callback
- per MEX file, which is called when the MEX file is flushed. (The problem with using
- mexAtExit, is that it's hard for any particular subroutine to know whether somebody
- else has already used up the single available slot in the call-back table.)
- In order to make your C subroutines as portable and autonomous as possible, you may
- prefer to use this AtExitToShell() which allows you to register lots of callback
- routines, and registers itself, once, with mexAtExit.
-
- CAUTION: Since MATLAB registers only one function per MEX it is important that
- you consistently adopt one strategy. Either make lots of calls to AtExitToShell
- (and NONE to mexAtExit), or just one call to mexAtExit. If you call both AtExitToShell
- and mexAtExit then one will displace the other in MATLAB's one-entry table.
-
- CODE FRAGMENT MANAGER:
-
- The following is quoted from C.S.M.P. Digest, Volume 4 : Issue 31, 02 Jan 97
-
- >From SouthSide@kagi.com (Bob Bradley)
- Date: Mon, 16 Dec 1996 20:53:48 -0800
- Organization: SPC
-
- In article <32B57B59.566A@kp.ssdn.skelleftea.se>,
- JSO0605@kp.ssdn.skelleftea.se [Johan Sˆrlin, johan.sorlin@mailbox.hogia.net] wrote:
-
- > Can anyone please tell me how to make a PPC ExitToShell Patch?
- > I need a PPC function of: AtExitToShell that i found in VideoToolbox.
-
- You can use the CFM Termination routine to do what an ExitToShell patch
- would do for non-CFM 68K code. Otherwise, you just need to create a
- RoutineDescriptor to your patched ExitToShell instead of passing just a
- ProcPtr to SetToolTrapAddress. [That's what the code below does--dgp]
-
- Check out the Code Fragment Manager chapter in Inside Mac: PowerPC System
- Software.
-
- +++++++++++++++++++++++++++
- >From mxmora@mxmdesigns.com (Matthew Xavier Mora)
- Date: Mon, 16 Dec 1996 21:55:08 -0800
- Organization: MXM DesignsÅ
-
- In article <32B57B59.566A@kp.ssdn.skelleftea.se>,
- JSO0605@kp.ssdn.skelleftea.se wrote:
-
- > Can anyone please tell me how to make a PPC ExitToShell Patch?
- > I need a PPC function of: AtExitToShell that i found in VideoToolbox.
-
-
- Install a CFM Termination routine. In MW look in the Linker
- pref panel (I think). Type in the name of the routine that you
- want called when your app exits.
-
- Xavier
-
- --
- Matthew Xavier Mora <mailto:mxmora@mxmdesigns.com>
- <http://www.best.com/~mxmora/mxm.html>
- +++++++++++++++++++++++++++
-
-
- HISTORY:
- 10/27/94 dgp wrote the ExitToShell patch, based on examples that appeared in UseNet
- csmp-digest-v3-046 by Kevin Bell (kbell@cs.utexas.edu) and Bill Hofmann
- (wdh@netcom.com) in response to a query by Steve Coy (stevec@jolt.mpx.com.au)
- 6/17/95 dgp wrote AtExitToShell.c
- 7/1/95 dgp made compatible with pre-universal apple headers.
- Disable if MATLAB is true. Added comments about MATLAB.
- 7/17/95 dgp made compatible with pre-universal headers
- 4/19/96 dgp call mexAtExit(). I know this is ok for PPC, but may not work for 68k.
- 6/10/96 dgp fixed initialization error when MATLAB is true.
- 6/10/96 dgp added a couple of paragraphs explaining its use in MATLAB MEX files.
- 6/11/96 dgp In response to concerns raised by David Brainard, I added text above
- warning about the danger of calling BOTH AtExitToShell and mexAtExit, and
- I made the A5 stuff conditional on !MATLAB.
- 8/5/96 dgp #undef mexAtExit to make sure we call the real McCoy.
- 1/9/97 dgp added csmp quote about CFM, above
- 4/10/97 dgp Eliminate stuff that was conditional on !UNIVERSAL_HEADERS.
- 7/9/97 dgp Polished some CFM comments above.
- */
- #ifndef _VIDEOTOOLBOX_
- #include "VideoToolbox.h"
- #endif
- #ifndef __TRAPS__
- #include <Traps.h> // _ExitToShell
- #endif
- #include <SegLoad.h> // ExitToShell()
- typedef UniversalProcPtr TrapAddressType;
- static pascal void MyExitToShell(void);
- #define FUNCTIONS 35
- static UniversalProcPtr oldExitToShellTrapAddress=NULL; // save address of real ExitToShell trap.
- static void (*userFunction[FUNCTIONS])(void); // table of user functions to be called at exit.
-
- int AtExitToShell(void (*userFunctionPtr)(void))
- {
- #if !MATLAB
- UniversalProcPtr myExitToShellUPP;
- #endif
- int i;
- static Boolean firstTime=1;
-
- if(firstTime){
- #if !MATLAB
- myExitToShellUPP=NewRoutineDescriptor((ProcPtr)MyExitToShell
- ,kPascalStackBased,GetCurrentISA());
- oldExitToShellTrapAddress=(UniversalProcPtr)GetToolTrapAddress(_ExitToShell);
- SetToolTrapAddress((TrapAddressType)myExitToShellUPP,_ExitToShell);
- #else
- // Ask MATLAB to call MyExitToShell just before disposing of our MEX resource.
- #undef mexAtExit
- mexAtExit((void *)MyExitToShell);
- #endif
- for(i=0;i<FUNCTIONS;i++)userFunction[i]=NULL;
- firstTime=0;
- }
- for(i=0;i<FUNCTIONS;i++)if(userFunction[i]==NULL){
- userFunction[i]=userFunctionPtr;
- return 0; // success
- }
- return 1; // failure: the table's already full
- }
-
- static pascal void MyExitToShell(void)
- {
- int i;
-
- #if !MATLAB
- SetCurrentA5();
- SetToolTrapAddress((TrapAddressType)oldExitToShellTrapAddress,_ExitToShell);
- #endif
-
- for(i=FUNCTIONS-1;i>=0;i--)if(userFunction[i]!=NULL){
- (*userFunction[i])();
- }
-
- #if !MATLAB
- ExitToShell();
- #endif
- }
-